package com.pingpang.netty.client;

import com.pingpang.common.bean.RequestBean;
import com.pingpang.common.bean.ResponseBean;
import com.pingpang.registry.SeverRegistry;
import com.pingpang.util.ThreadPoolUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadPoolExecutor;

@Component
public class RpcFactory<T> implements InvocationHandler {

	@Autowired
	private NettyClient client;
	private  final ThreadPoolExecutor threadPool=ThreadPoolUtil.getThreadPool(10,30); 
	private Logger logger = LoggerFactory.getLogger(this.getClass());
    
	/**
	 * 默认IP 端口
	 */
	private String ip;
	private int port;
	
	/**
	 * 默认设置
	 * ip   127.0.0.1
	 * port 18868
	 */
	public RpcFactory() {
		this.ip="127.0.0.1";
		this.port=18868;
	}
	
	/**
	 * 设置IP 端口
	 * @param ip
	 * @param port
	 */
	public RpcFactory(String ip,int port) {
		this.ip=ip;
		this.port=port;
	}
	
	
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		return threadPool.submit(new Callable<Object>() {

			@Override
			public Object call() throws Exception {
				try {
					if(null==client) {
						client = new NettyClient();
					}
					//获取IP地址开始
					logger.info("【通过zookeeper获取服务端地址开始】");
					SeverRegistry sr=SeverRegistry.getServerRegistry();
					List<String> ipList=sr.getServerPath(method.getDeclaringClass().getName());
					for(String str:ipList) {
						logger.info("服务名称{},地址{}",method.getDeclaringClass().getName(),str);
						ip=str.split(":")[0];
						port=Integer.valueOf(str.split(":")[1]);
					}
					logger.info("【通过zookeeper获取服务端地址结束】");
					
					String requestID = UUID.randomUUID().toString().replace("-", "");
					RequestBean request = new RequestBean();
					request.setClassName(method.getDeclaringClass().getName());
					request.setMethodName(method.getName());
					request.setParameters(args);
					request.setParameterTypes(method.getParameterTypes());
					request.setId(requestID);
					request.setIp(ip);
					request.setPort(port);
					Object result = client.send(request);
					Class<?> returnType = method.getReturnType();
					ResponseBean response = (ResponseBean) result;
					if(-1==response.getCode()) {
						throw new Exception(response.getErrorMsg());
					}
					return response.getData();
				} catch (Exception e) {
					logger.error("调用失败:" + e.getMessage(), e);
					throw new Exception(e.getMessage());
				} finally {
					//关闭channel 客户端还可以复用
					/*
					 * if(null!=client) { client.destroy(); client = null; }
					 */
				}
			}
		}).get();
		
		/*
		 * try { if (null == client) { client = new NettyClient(); } String requestID =
		 * UUID.randomUUID().toString().replace("-", ""); RequestBean request = new
		 * RequestBean(); request.setClassName(method.getDeclaringClass().getName());
		 * request.setMethodName(method.getName()); request.setParameters(args);
		 * request.setParameterTypes(method.getParameterTypes());
		 * request.setId(requestID); request.setIp(ip); request.setPort(port); Object
		 * result = client.send(request); Class<?> returnType = method.getReturnType();
		 * ResponseBean response = (ResponseBean) result; if (-1 == response.getCode())
		 * { throw new Exception(response.getErrorMsg()); } return response.getData(); }
		 * catch (Exception e) { logger.error("调用失败:" + e.getMessage(), e); throw new
		 * Exception(e.getMessage()); } finally { if (null != client) {
		 * client.destroy(); client = null; } }
		 */
		 
	}

	public NettyClient getClient() {
		return client;
	}

	public void setClient(NettyClient client) {
		this.client = client;
	}

	public void closeThreadPool() {
		if(null!=this.threadPool && !this.threadPool.isShutdown()) {
			this.threadPool.shutdown();
		}
	}
}
